﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CCPnuts.Pack;
using CCPnuts.ISkyDiskFileSystem.Interfaces;
using CCPnuts.Base;

namespace CCPnuts.ISkyDiskFileSystem
{
    public delegate void TransmissionUpdateEvent(Transmitor sender);

    /// <summary>
    /// Represent a transmission.
    /// </summary>
    public abstract class Transmitor : PackerBase
    {
        #region Packed Target

        internal Transmitor(IPacked packed)
            : base(packed)
        {
            ((I_Transmitor)packed).TransmissionUpdate += () =>
            {
                if (this.TransmissionUpdate != null) { this.TransmissionUpdate(this); }
            };
        }

        internal new I_Transmitor Packed { get { return (I_Transmitor)base.Packed; } }

        #endregion

        #region Proxy Members

        public event TransmissionUpdateEvent TransmissionUpdate;

        #region Essential Members

        /// <summary>
        /// Begin a Synchronous transmission.
        /// Return till the transmission is finish.
        /// </summary>
        public void Run()
        {
            Packed.Run();
        }

        /// <summary>
        /// Stop a transmission.
        /// </summary>
        public void Stop()
        {
            Packed.Stop();
        }

        /// <summary>
        /// Gets the number of bytes to send.
        /// </summary>
        public long TotalToSend { get { return Packed.TotalToSend; } }


        /// <summary>
        /// Gets the number of bytes has sent.
        /// </summary>
        public long Sent { get { return Packed.Sent; } }

        /// <summary>
        /// Gets the speed of the transmission.
        /// </summary>
        public int Speed { get { return Packed.Speed; } }

        /// <summary>
        /// Gets the state of the transmission.
        /// </summary>
        public TransmissionStateTypes TransmissionState { get { return Packed.TransmissionState; } }

        #endregion

        #region Optional Members

        /// <summary>
        /// Begin a asynchronous transmission.
        /// </summary>
        /// <returns></returns>
        [Optional]
        public IAsyncResult BeginRun(AsyncCallback callback)
        {
            try
            {
                return Packed.BeginRun(callback);
            }
            catch (NotImplementedException)
            {
                var dele = new AsyncReturnDelegate(this.Run);
                return dele.BeginInvoke(callback, dele);
            }
        }

        /// <summary>
        /// End a asynchronous transmission.
        /// </summary>
        /// <param name="result"></param>
        [Optional]
        public void EndRun(IAsyncResult result)
        {
            try
            {
                Packed.EndRun(result);
            }
            catch (NotImplementedException)
            {
                var dele = (AsyncReturnDelegate)result.AsyncState;
                dele.EndInvoke(result);
            }
        }

        /// <summary>
        /// Pause a transmision.
        /// </summary>
        [Optional]
        public void Pause()
        {
            try
            {
                Packed.Pause();
            }
            catch (NotImplementedException)
            {
                throw new NotSupportedException("NotSupported @ Transmitor : Pause");
            }
        }

        /// <summary>
        /// Resume a transmission.
        /// </summary>
        [Optional]
        public void Resume()
        {
            try
            {
                Packed.Resume();
            }
            catch (NotImplementedException)
            {
                throw new NotSupportedException("NotSupport @ Transmitor : Resume");
            }
        }

        #endregion

        #endregion

        #region Own Members

        public abstract TransmissionTypes TransmissionType { get; }

        #endregion
    }
}
